﻿//-----------------------------------------------------------------------
// <copyright file="Address.cs" company="Craig Longford (deltawolf7@gmail.com)">
//     Copyright (c) Craig Longford. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace Delta.Mercury.Business.User
{
    using System;
    using Delta.Data.DataExpress;
    using Delta.Mercury.Business.Exceptions;

    /// <summary>
    /// Address or a person
    /// </summary>
    [Serializable]
    public class Address : IdentifierBase, IDataServicable, IAddress
    {
        #region Members
        /// <summary>
        /// Address Line 1
        /// </summary>
        private string addressLine1;

        /// <summary>
        /// Address Line 2
        /// </summary>
        private string addressLine2;

        /// <summary>
        /// Address Line 3
        /// </summary>
        private string addressLine3;

        /// <summary>
        /// Address City
        /// </summary>
        private string addresCityValue;

        /// <summary>
        /// Address Region
        /// </summary>
        private string addresRegionValue;

        /// <summary>
        /// Address Post Code
        /// </summary>
        private string addresPostCodeValue;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the Address class.
        /// </summary>
        public Address()
            : this(Guid.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty)
        {
        }

        /// <summary>
        /// Initializes a new instance of the Address class.
        /// </summary>
        /// <param name="ownerGuid">Owner unique indetifier</param>
        /// <param name="addressLine1">Address line 1</param>
        /// <param name="addressLine2">Address line 2</param>
        /// <param name="addressLine3">Address line 3</param>
        /// <param name="addressCity">Address city</param>
        /// <param name="addressRegion">Address region</param>
        /// <param name="addressPostCode">Address post code</param>
        public Address(Guid ownerGuid, string addressLine1, string addressLine2, string addressLine3, string addressCity, string addressRegion, string addressPostCode)
            : this(ownerGuid, addressLine1, addressLine2, addressLine3, addressCity, addressRegion, addressPostCode, false, false)
        {
        }

        /// <summary>
        /// Initializes a new instance of the Address class.
        /// </summary>
        /// <param name="ownerGuid">Owner unique indetifier</param>
        /// <param name="addressLine1">Address line 1</param>
        /// <param name="addressLine2">Address line 2</param>
        /// <param name="addressLine3">Address line 3</param>
        /// <param name="addressCity">Address city</param>
        /// <param name="addressRegion">Address region</param>
        /// <param name="addressPostCode">Address post code</param>
        /// <param name="preferedBilling">Prefered billing address</param>
        /// <param name="preferedDelivery">Prefered delivery address</param>
        public Address(Guid ownerGuid, string addressLine1, string addressLine2, string addressLine3, string addressCity, string addressRegion, string addressPostCode, bool preferedBilling, bool preferedDelivery)
            : base()
        {
            this.OwnerGuid = ownerGuid;
            this.addresCityValue = addressCity;
            this.addresPostCodeValue = addressPostCode;
            this.addresRegionValue = addressRegion;
            this.addressLine1 = addressLine1;
            this.addressLine2 = addressLine2;
            this.addressLine3 = addressLine3;
            this.PreferedBilling = preferedBilling;
            this.PreferedDelivery = preferedDelivery;
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the owner unique identifier
        /// </summary>
        public virtual Guid OwnerGuid { get; set; }

        /// <summary>
        /// Gets or sets address line 1
        /// </summary>
        public virtual string Line1
        {
            get
            {
                return this.addressLine1;
            }

            set
            {
                if (value.Length < 1)
                {
                    throw new InvalidLengthException("Address line 1 must be a minimum of 1 characters.");
                }

                if (value.Length > 50)
                {
                    throw new InvalidLengthException("Address line 1 must be a maximum of 50 characters.");
                }

                this.addressLine1 = value;
            }
        }

        /// <summary>
        /// Gets or sets address line 2
        /// </summary>
        public virtual string Line2
        {
            get
            {
                return this.addressLine2;
            }

            set
            {
                if (value.Length > 50)
                {
                    throw new InvalidLengthException("Address line 2 must be a maximum of 50 characters.");
                }

                this.addressLine2 = value;
            }
        }

        /// <summary>
        /// Gets or sets address line 3
        /// </summary>
        public virtual string Line3
        {
            get
            {
                return this.addressLine2;
            }

            set
            {
                if (value.Length > 50)
                {
                    throw new InvalidLengthException("Address line 3 must be a maximum of 50 characters.");
                }

                this.addressLine3 = value;
            }
        }

        /// <summary>
        /// Gets or sets address city
        /// </summary>
        public virtual string City
        {
            get
            {
                return this.addresCityValue;
            }

            set
            {
                if (value.Length < 1)
                {
                    throw new InvalidLengthException("Address city must be a minimum of 1 characters.");
                }

                if (value.Length > 30)
                {
                    throw new InvalidLengthException("Address city must be a maximum of 50 characters.");
                }

                this.addresCityValue = value;
            }
        }

        /// <summary>
        /// Gets or sets address region
        /// </summary>
        public virtual string Region
        {
            get
            {
                return this.addresRegionValue;
            }

            set
            {
                if (value.Length < 1)
                {
                    throw new InvalidLengthException("Address region must be a minimum of 1 characters.");
                }

                if (value.Length > 30)
                {
                    throw new InvalidLengthException("Address region must be a maximum of 50 characters.");
                }

                this.addresRegionValue = value;
            }
        }

        /// <summary>
        /// Gets or sets address post code
        /// </summary>
        public virtual string PostCode
        {
            get
            {
                return this.addresPostCodeValue;
            }

            set
            {
                if (value.Length < 1)
                {
                    throw new InvalidLengthException("Address post code must be a minimum of 1 characters.");
                }

                if (value.Length > 30)
                {
                    throw new InvalidLengthException("Address post code must be a maximum of 10 characters.");
                }

                this.addresPostCodeValue = value.ToUpper();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the address is the prefered billing address.
        /// </summary>
        public virtual bool PreferedBilling { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the address is the prefered delivery address.
        /// </summary>
        public virtual bool PreferedDelivery { get; set; }
        #endregion

        #region Load Methods
        /// <summary>
        /// Load address from database
        /// </summary>
        /// <param name="guid">Unique identifier</param>
        /// <param name="showDeleted">Show deleted</param>
        /// <returns>Filled address</returns>
        public static Address Load(Guid guid, bool showDeleted)
        {
            Parameters parameters = new Parameters();
            parameters.Add(new Parameter("Guid", guid));
            parameters.Add(new Parameter("Deleted", showDeleted));
            return DataAccess.GetSingle<Address>("LoadAddress", System.Data.CommandType.StoredProcedure, parameters);
        }
        #endregion

        #region Fill Method
        /// <summary>
        /// Fill from database
        /// </summary>
        /// <param name="reader">Database reader</param>
        public virtual void Fill(System.Data.IDataReader reader)
        {
            this.addresCityValue = Helper.ToString(reader["City"]);
            this.addresPostCodeValue = Helper.ToString(reader["PostCode"]);
            this.addresRegionValue = Helper.ToString(reader["Region"]);
            this.addressLine1 = Helper.ToString(reader["Line1"]);
            this.addressLine2 = Helper.ToString(reader["Line2"]);
            this.addressLine3 = Helper.ToString(reader["Line3"]);
            this.Guid = Helper.ToGuid(reader["Guid"]);
            this.OwnerGuid = Helper.ToGuid(reader["OwnerGuid"]);
            this.PreferedDelivery = Helper.ToBool(reader["PreferedDelivery"]);
            this.PreferedBilling = Helper.ToBool(reader["PreferedBilling"]);
        }
        #endregion

        #region Save Methods
        /// <summary>
        /// Save object to database
        /// </summary>
        public virtual void Save()
        {
            DataAccess.NonQuery("SaveAddress", System.Data.CommandType.StoredProcedure, GetSaveParameters());
        }
        #endregion

        #region Delete Methods
        /// <summary>
        /// Delete address from database
        /// </summary>
        public virtual void Delete()
        {
            Parameters parameters = new Parameters();
            parameters.Add(new Parameter("Guid", this.Guid));
            DataAccess.NonQuery("DeleteAddress", System.Data.CommandType.StoredProcedure, parameters);
        }
        #endregion

        #region Get Save Parameters
        public Parameters GetSaveParameters()
        {
            Parameters parameters = new Parameters();
            parameters.Add(new Parameter("Guid", this.Guid));
            parameters.Add(new Parameter("OwnerGuid", this.OwnerGuid));
            parameters.Add(new Parameter("Line1", this.Line1));
            parameters.Add(new Parameter("Line2", this.Line2));
            parameters.Add(new Parameter("Line3", this.Line3));
            parameters.Add(new Parameter("City", this.City));
            parameters.Add(new Parameter("Region", this.Region));
            parameters.Add(new Parameter("PostCode", this.PostCode));
            parameters.Add(new Parameter("PreferedBilling", this.PreferedBilling));
            parameters.Add(new Parameter("PreferedDelivery", this.PreferedDelivery));
            return parameters;
        }
        #endregion
    }
}
